/*
 * Operand.cpp
 *
 *  Created on: 2009-11-26
 *      Author: ws
 */

#include "Operand.hpp"
#include"Value.hpp"
#include"Operation.hpp"

#define CAST_TEMPLATE( XXXOperand,TYPE )\
XXXOperand * XXXOperand##_cast(Operand * opd)\
{\
	if(opd->get_type() == TYPE)\
		return (XXXOperand *)opd;\
	else\
		return NULL;\
}


#define CONST_CAST_TEMPLATE(XXXOperand,TYPE )\
XXXOperand const * XXXOperand##_cast ( Operand const * opd)\
{\
	if(opd->get_type() == TYPE)\
		return (XXXOperand const *)opd;\
	else\
		return NULL;\
}

CONST_CAST_TEMPLATE( SimdOperand, SIMD_OPD)
CAST_TEMPLATE ( SimdOperand, SIMD_OPD)

CONST_CAST_TEMPLATE( DataOperand, DATA_OPD)
CAST_TEMPLATE( DataOperand, DATA_OPD)

CONST_CAST_TEMPLATE( AddrOperand, ADDR_OPD)
CAST_TEMPLATE( AddrOperand, ADDR_OPD)




Operand::~Operand() {
}

Value * AddrOperand::get_value()
{
	return v;
}


Value * DataOperand::get_value()
{
	return v;
}

std::vector<RegValue*> SimdOperand::get_values()
{
	return regs;
}

std::vector<int> SimdOperand::get_ids()const
{
	std::vector<int> ids ;
	for(int i = 0;i < regs.size(); i++)
	{
		ids.push_back(regs[i]->get_id());
	}
	return ids;
}

bool SimdOperand::have_a(Value *v)
{
	for(int i = 0; i < regs.size(); i++)
	{
		if((*regs[i]) == *v)
			return true;
	}
	return false;
}

bool DataOperand::have_a(Value *t)
{
	return (*v) == (*t);
}

bool AddrOperand::have_a(Value *t)
{
	return *t == *v;
}

void AddrOperand::build_value(std::vector<Value*> & vs)const
{
	vs.push_back(v);
}
void DataOperand::build_value(std::vector<Value*> &vs)const
{
	vs.push_back(v);
}

void SimdOperand::build_value(std::vector<Value*> &vs)const
{
	for(int i = 0; i < regs.size(); i++)
	{
		vs.push_back(regs[i]);
	}
}



bool operator == (Operand const & x, Operand const & y)
{
	if(x.get_type() != y.get_type())
	{
		return false;
	}
	else
	{
		switch(x.get_type() )
		{
		case SIMD_OPD:
			const SimdOperand * sx = SimdOperand_cast(&x);
			const SimdOperand * sy = SimdOperand_cast(&y);
			assert(sx);
			assert(sy);
			for(int i = 0; i < 8; i++)
			{
				if((*(sx->regs[i])) != (*(sy->regs[i])))
				{
					return false;	
				}
			}
			return true;
		case ADDR_OPD:
			const AddrOperand * ax = AddrOperand_cast(&x);	
			const AddrOperand * ay = AddrOperand_cast(&y);
			assert(ax);
			assert(ay);
			if( (*(ax->v)) == (*(ay->v)))	
				return true;
			else 
				return false;
		case DATA_OPD:
			const DataOperand * dx = DataOperand_cast(&x);
			const DataOperand * dy = DataOperand_cast(&y);
			assert(dx);
			assert(dy);
			if((*(dx->v)) == (*(dy->v)))
				return true;
			else
				return false;
		default:
			assert("error" == "unexpected operand type");
		}
	}
}

